package com.csx.micrometer.database.timer;

import com.csx.micrometer.common.util.MetricsUtil;
import com.csx.micrometer.database.config.MicrometerDatabaseProperties;
import com.csx.micrometer.database.model.DatabaseEncapsulation;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.Tags;
import org.springframework.scheduling.annotation.Scheduled;

import javax.annotation.PostConstruct;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
 * @author cuisongxu
 * @date 2023/3/14 20:06
 */
public class DatabasesMonitor {

    private final MicrometerDatabaseProperties micrometerDatabaseProperties;

    private Map<String, DatabaseEncapsulation> map = new HashMap<>();

    public DatabasesMonitor(MicrometerDatabaseProperties micrometerDatabaseProperties) {
        this.micrometerDatabaseProperties = micrometerDatabaseProperties;
    }

    @PostConstruct
    public void init() throws ClassNotFoundException, SQLException{

        Map<String, MicrometerDatabaseProperties.Database> databases =
                micrometerDatabaseProperties.getDatabases();

        // TODO 将这块初始化的代码转换到初始化中
        for (Map.Entry<String, MicrometerDatabaseProperties.Database> entry : databases.entrySet()) {
            String databaseName = entry.getKey();
            MicrometerDatabaseProperties.Database databaseInfo = entry.getValue();

            String driverClassName = databaseInfo.getDriverClassName();
            String url = databaseInfo.getUrl();
            String username = databaseInfo.getUsername();
            String password = databaseInfo.getPassword();

            String tableName = databaseInfo.getTableName();

            String region = databaseInfo.getRegion();
            String zone = databaseInfo.getZone();

            Class.forName(driverClassName);
            Connection conn = DriverManager.getConnection(url, username, password);
            String sql = "select count(1) AS count from " + tableName;

            DatabaseEncapsulation databaseEncapsulation = new DatabaseEncapsulation();
            databaseEncapsulation.setConnection(conn);
            databaseEncapsulation.setSql(sql);
            databaseEncapsulation.setRegion(region);
            databaseEncapsulation.setZone(zone);
            map.put(databaseName, databaseEncapsulation);
        }
    }

    @Scheduled(cron = "0/2 * * * * ?")
    public void monitor() throws SQLException {
        for (Map.Entry<String, DatabaseEncapsulation> entry : map.entrySet()) {
            String databaseName = entry.getKey();
            DatabaseEncapsulation databaseEncapsulation = entry.getValue();

            String region = databaseEncapsulation.getRegion();
            String zone = databaseEncapsulation.getZone();
            String sql = databaseEncapsulation.getSql();
            Connection conn = databaseEncapsulation.getConnection();

            Properties clientInfo = conn.getClientInfo();
            int holdability = conn.getHoldability();
            String catalog = conn.getCatalog();
            DatabaseMetaData metaData = conn.getMetaData();
            Map<String, Class<?>> typeMap = conn.getTypeMap();


            Statement statement = conn.createStatement();
            ResultSet resultSet = statement.executeQuery(sql);

            int count = 0;
            while (resultSet.next()) {
                count = resultSet.getInt("count");
            }
            Tag regionTag = Tag.of("region", region);
            Tag zoneTag = Tag.of("zone", zone);
            Tags tags = Tags.of(regionTag, zoneTag);
            // TODO 将信息封装并保留给 Exporter
            MetricsUtil.gauge("database_access", count, tags);
        }
    }

}
